#include "stdafx.h"
#include "Log.h"
#include "LogFile.h"
#include "../Core/CoreException.h"

namespace Core
{
	LogFileWriter::LogFileWriter()
	{
		m_FStream = NULL;
		m_FileTime = 0;
		m_LogFileInterval = LogFileInterval_EveryDay;
	}

	LogFileWriter::~LogFileWriter()
	{
		FinalizeFStream();
	}

	void LogFileWriter::SetFileNameMask(std::string p_FileNameMask)
	{
		m_FileNameMask = p_FileNameMask;
	}

	void LogFileWriter::SetInterval(LogFileIntervals p_LogFileInterval)
	{
		m_LogFileInterval = p_LogFileInterval;
	}

	void LogFileWriter::FinalizeFStream()
	{
		if(m_FStream)
		{
			m_FStream->close();
			delete m_FStream;
			m_FStream = NULL;
		}
	}

	bool LogFileWriter::IsExpired()
	{
		DateTime t_DateTime;
		if(m_LogFileInterval==LogFileInterval_EverySecond)
		{
			return (t_DateTime.GetSecond()!=m_FileTime.GetSecond());
		}
		else if(m_LogFileInterval==LogFileInterval_EveryMinute)
		{
			return (t_DateTime.GetMinute()!=m_FileTime.GetMinute());
		}
		else if(m_LogFileInterval==LogFileInterval_EveryHour)
		{
			return (t_DateTime.GetHour()!=m_FileTime.GetHour());
		}
		else if(m_LogFileInterval==LogFileInterval_EveryDay)
		{
			return (t_DateTime.GetDate()!=m_FileTime.GetDate());
		}
		else if(m_LogFileInterval==LogFileInterval_EveryMonth)
		{
			return (t_DateTime.GetMonth()!=m_FileTime.GetMonth());
		}
		else if(m_LogFileInterval==LogFileInterval_EveryYear)
		{
			return (t_DateTime.GetYear()!=m_FileTime.GetYear());
		}
		return false;
	}

	std::ofstream& LogFileWriter::GetStream()
	{
		CheckFileName();
		return *m_FStream;
	}

	void LogFileWriter::CheckFileName()
	{
		if((m_FileTime.GetTotalSeconds()==0) || IsExpired())
		{
			FinalizeFStream();
			m_FileTime = DateTime();
			m_FStream = new std::ofstream(m_FileTime.ToString(m_FileNameMask).c_str(), std::ios_base::out | std::ios_base::app | std::ios_base::binary);
		}
	}

	void LogFileWriter::WriteRawData(RawData& p_RawData, InternetAddress p_SenderAddress, InternetAddress p_ReceiverAddress, TimeSpan p_TimeSpan)
	{
		try
		{
			p_RawData.ResetReadIterator();
			std::ofstream& t_OFStream = GetStream();
			RawData t_RawData;
			t_RawData.WriteLong(p_TimeSpan.GetSecond());
			t_RawData.WriteShort(p_TimeSpan.GetMilliSecond());
			t_RawData.WriteLong(p_SenderAddress.GetAddress());
			t_RawData.WriteShort(p_SenderAddress.PortNumber);
			t_RawData.WriteLong(p_ReceiverAddress.GetAddress());
			t_RawData.WriteShort(p_ReceiverAddress.PortNumber);
			t_RawData.WriteShort(p_RawData.GetLength());
			t_RawData.WriteToOStream(t_OFStream, 20);
			p_RawData.WriteToOStream(t_OFStream, p_RawData.GetLength());
			t_OFStream.flush();
		}
		catch(...)
		{
			Log::GetSingleton().Write(LogLevel_Error, "Error while writing Raw Data to Log File");
		}
	}


	LogFileReader::LogFileReader()
	{
		m_EarliestData = 0;
	}
	
	void LogFileReader::Open(std::string p_FileName, bool p_Analyze)
	{
		m_FileName = p_FileName;
		m_FStream.open(p_FileName.c_str(), std::ios_base::in | std::ios_base::binary);
		if(!m_FStream)
		{
			throw FileException();
		}
		if(!p_Analyze) return;
		m_NumberOfRawData = 0;
		RawData t_RawData;
		InternetAddress t_SenderAddress;
		InternetAddress t_ReceiverAddress;
		TimeSpan t_TimeSpan;
		while(!m_FStream.eof())
		{
			m_NumberOfRawData++;
			std::cout << ".";
			try
			{
				ReadRawData(t_RawData, t_SenderAddress, t_ReceiverAddress, t_TimeSpan);
			}
			catch(...)
			{
				break;
			}
			if(m_EarliestData.GetTotalSeconds()==0)
			{
				m_EarliestData = t_TimeSpan.GetSecond();
			}
			{
				m_LatestData = t_TimeSpan.GetSecond();
			}
		}
		m_FStream.close();
		m_FStream.open(p_FileName.c_str(), std::ios_base::in | std::ios_base::binary);
	}

	void LogFileReader::Close()
	{
		m_FStream.close();
	}

	bool LogFileReader::IsEOF()
	{
		return m_FStream.eof();
	}

	void LogFileReader::ReadRawData(RawData& p_RawData, InternetAddress& p_SenderAddress, InternetAddress& p_ReceiverAddress, TimeSpan& p_TimeSpan)
	{
		if((!m_FStream) || (m_FStream.eof())) throw FileException();
		RawData t_RawData;
		unsigned long t_Long;
		unsigned short t_Shorts;
		t_RawData.ReadFromIStream(m_FStream, 20);
		t_Long = t_RawData.ReadLong();
		t_Shorts = t_RawData.ReadShort();
		p_TimeSpan.SetTime(t_Long, t_Shorts);
		t_Long = t_RawData.ReadLong();
		t_Shorts = t_RawData.ReadShort();
		p_SenderAddress.SetAddress(t_Long);
		p_SenderAddress.PortNumber = t_Shorts;
		t_Long = t_RawData.ReadLong();
		t_Shorts = t_RawData.ReadShort();
		p_ReceiverAddress.SetAddress(t_Long);
		p_ReceiverAddress.PortNumber = t_Shorts;
		t_Shorts = t_RawData.ReadShort();
		p_RawData.Reset();
		p_RawData.ReadFromIStream(m_FStream, t_Shorts);
	}

	std::string LogFileReader::GetFileName()
	{
		return m_FileName;
	}

	unsigned int LogFileReader::GetNumberOfRawData()
	{
		return m_NumberOfRawData;
	}

	DateTime LogFileReader::GetEarliestData()
	{
		return m_EarliestData;
	}

	DateTime LogFileReader::GetLatestData()
	{
		return m_LatestData;
	}
}
